home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1999 January: Mac OS SDK / Dev.CD Jan 99 SDK1.toast / Development Kits / Mac OS USB DDK_v1.0.1 / Examples / CompositeClassDriver / CompositeClassDriver.c next >
Encoding:
C/C++ Source or Header  |  1998-09-03  |  9.4 KB  |  255 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CompositeClassDriver.c
  3.  
  4.     Contains:    Core functionality to Composite Class Driver
  5.  
  6.     Version:    xxx put version here xxx
  7.  
  8.     Copyright:    © 1997-1998 by Apple Computer, Inc., all rights reserved.
  9.  
  10. */
  11.  
  12. #include <Types.h>
  13. #include <Devices.h>
  14. #include <processes.h>
  15. #include <DriverServices.h>
  16. #include <USB.h>
  17.  
  18. #include "CompositeClassDriver.h"
  19. extern    usbCompositePBStruct myCompositePBRecord;
  20.  
  21.  
  22. void InitParamBlock(USBDeviceRef theDeviceRef, USBPB * paramblock)
  23. {
  24.     paramblock->usbReference = theDeviceRef;
  25.     paramblock->usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  26.     paramblock->pbLength = sizeof(usbCompositePBStruct);
  27.     paramblock->pbVersion = kUSBCurrentPBVersion;
  28.     paramblock->usbWIndex = 0;             
  29.     paramblock->usbBuffer = nil;        
  30.     paramblock->usbStatus = kUSBNoErr;
  31.     paramblock->usbReqCount = 0;
  32.     paramblock->usbActCount = 0;
  33.     paramblock->usbWValue = 0;
  34.     paramblock->usbFlags = 0;
  35. }
  36.  
  37.  
  38. Boolean immediateError(OSStatus err)
  39. {
  40.     return((err != kUSBPending) && (err != kUSBNoErr) );
  41. }
  42.  
  43. void CompositeDeviceInitiateTransaction(USBPB *pb)
  44. {
  45. register usbCompositePBStruct *pCompositePB;
  46. OSStatus myErr;
  47.  
  48.     pCompositePB = (usbCompositePBStruct *)(pb);
  49.     pCompositePB->transDepth++;
  50.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  51.     {
  52.     
  53.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Illegal Transaction Depth", pCompositePB->pb.usbRefcon);
  54.     }
  55.     do 
  56.     {
  57.         switch(pCompositePB->pb.usbRefcon & ~kRetryTransaction)
  58.         {
  59.             case kGetFullConfiguration0:
  60.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  61.                 pCompositePB->pb.usbWIndex = 0;             /* First try configuration 0, if it doesn't succeed, then try config 1*/
  62.                 
  63.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  64.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  65.                 myErr = USBGetFullConfigurationDescriptor(pb);
  66.                 if(immediateError(myErr))
  67.                 {
  68.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#0) - immediate error", myErr);
  69.                 }
  70.                 break;
  71.             
  72.             case kGetFullConfiguration1:
  73.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  74.                 pCompositePB->pb.usbWIndex = 1;             /* Try configuration 1 (some devices seem to expect config 0, others config 1 */
  75.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  76.                 
  77.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  78.                 myErr = USBGetFullConfigurationDescriptor(pb);
  79.                 if(immediateError(myErr))
  80.                 {
  81.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration (#1) - immediate error", myErr);
  82.                 }
  83.                 break;
  84.             
  85.             case kSetConfig:
  86.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  87.                 pCompositePB->pb.usbBMRequestType = USBMakeBMRequestType(kUSBOut, kUSBStandard, kUSBDevice);
  88.                 
  89.                 pCompositePB->pb.usbBRequest = kUSBRqSetConfig;
  90.                 pCompositePB->pb.usbWValue = pCompositePB->pFullConfigDescriptor->configValue;         /* Use configuration ID value from descriptor */
  91.                 
  92.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  93.                 
  94.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  95.                 myErr = USBDeviceRequest(pb);
  96.                 if(immediateError(myErr))
  97.                 {
  98.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kSetConfig - immediate error", myErr);
  99.                 }
  100.                 break;
  101.                 
  102.             case kNewInterfaceRef:
  103.                 InitParamBlock(pCompositePB->deviceRef, &pCompositePB->pb);
  104.                 // Note: pCompositePB->usbWIndex will be set to zero by InitParamBlock
  105.                 // so set it again to pCompositePB->interfaceIndex before calling USBNewInterfaceRef
  106.                 pCompositePB->pb.usbWIndex = pCompositePB->interfaceIndex;
  107.                 pCompositePB->pb.usbRefcon |= kCompletionPending;
  108.                 pCompositePB->pb.usbCompletion = (USBCompletion)CompositeDeviceCompletionProc;
  109.  
  110.                 myErr = USBNewInterfaceRef(pb);
  111.                 if(immediateError(myErr))
  112.                 {
  113.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: kNewInterfaceRef - immediate error", myErr);
  114.                 }
  115.                 break;
  116.                 
  117.             default:
  118.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction initiated with bad refcon value", pCompositePB->pb.usbRefcon);
  119.                 pCompositePB->pb.usbRefcon = kUndefined + kExitDriver;
  120.                 break;
  121.         }
  122.     } while (false);
  123.     
  124. // At this point the control is returned to the system.  If a USB transaction
  125. // has been initiated, then it will call the Complete procs
  126. // (below) to handle the results of the transaction.
  127. }
  128.  
  129. void CompositeDeviceCompletionProc(USBPB *pb)
  130. {
  131. OSStatus myErr;
  132. register usbCompositePBStruct *pCompositePB;
  133. USBInterfaceDescriptorPtr pInterfaceDescriptor;
  134. UInt32 i;
  135.  
  136.     pCompositePB = (usbCompositePBStruct *)(pb);
  137.     pCompositePB->transDepth--;
  138.     if ((pCompositePB->transDepth < 0) || (pCompositePB->transDepth > 1))
  139.     {
  140.         USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Illegal Transaction Depth", pCompositePB->transDepth);
  141.     }
  142.     
  143.     if((pCompositePB->pb.usbStatus != kUSBNoErr) && (pCompositePB->pb.usbStatus != kUSBPending))
  144.     {
  145.         USBExpertStatus(pCompositePB->pb.usbReference, "\pComposite Driver: Completion Error", pCompositePB->pb.usbStatus);
  146.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
  147.         pCompositePB->pb.usbRefcon |= kRetryTransaction;
  148.         pCompositePB->retryCount--;
  149.         if (!pCompositePB->retryCount)
  150.         {
  151.             if (pCompositePB->pb.usbRefcon == kGetFullConfiguration1)
  152.             {
  153.                 pCompositePB->pb.usbRefcon = kGetFullConfiguration0;
  154.             }
  155.             else
  156.             {
  157.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: Too many retries", pCompositePB->pb.usbRefcon);
  158.                 pCompositePB->pb.usbRefcon = kExitDriver;
  159.                 return;
  160.             }
  161.         }
  162.     }
  163.     else
  164.     {
  165.         pCompositePB->pb.usbRefcon &= ~kRetryTransaction;
  166.         pCompositePB->retryCount = kCompositeRetryCount;
  167.     }
  168.  
  169.     if (pCompositePB->pb.usbRefcon & kCompletionPending)             
  170.     {                                                
  171.         pCompositePB->pb.usbRefcon &= ~(kCompletionPending + kExitDriver);
  172.         switch(pCompositePB->pb.usbRefcon)
  173.         {
  174.             case kGetFullConfiguration0:
  175.             case kGetFullConfiguration1:
  176. //                DebugStr("\pCheck power");
  177.                 pCompositePB->pFullConfigDescriptor = pCompositePB->pb.usbBuffer;
  178.                 if (pCompositePB->pFullConfigDescriptor == nil)
  179.                 {
  180.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver: USBGetFullConfiguration - pointer is nil", pCompositePB->pb.usbRefcon);
  181.                     pCompositePB->pb.usbRefcon = kExitDriver;
  182.                     break;
  183.                 }
  184.                 
  185.                 BlockCopy(   (void *)pCompositePB->pFullConfigDescriptor, (void *)(&(pCompositePB->partialConfigDescriptor)), (Size)(sizeof(USBConfigurationDescriptor) )  );
  186.                 if (pCompositePB->pFullConfigDescriptor->maxPower <= pCompositePB->busPowerAvailable)
  187.                 {
  188.                     pCompositePB->pb.usbRefcon = kSetConfig;
  189.                 }
  190.                 else
  191.                 {
  192.                     USBExpertSetDevicePowerStatus(pCompositePB->pb.usbReference, 0, 0, kUSBDevicePower_BusPowerInsufficient, pCompositePB->busPowerAvailable, pCompositePB->pFullConfigDescriptor->maxPower);
  193.                     USBExpertFatalError(pCompositePB->pb.usbReference, kUSBDevicePowerProblem, "\pComposite Driver - Insufficient power for device", pCompositePB->pb.usbRefcon);
  194.                     pCompositePB->pb.usbRefcon = kExitDriver;
  195.                 }
  196.                 break;
  197.                 
  198.             case kSetConfig:            /* get all the interface descriptors and save them */
  199.                 for (i=0; i < pCompositePB->partialConfigDescriptor.numInterfaces; i++)
  200.                 {
  201.                     pCompositePB->interfaceRefArray[i] = 0;
  202.                     myErr = GetInterfaceDescriptor(pCompositePB->pFullConfigDescriptor, (UInt32)i, &pInterfaceDescriptor);
  203.                     if (kUSBNoErr == myErr)
  204.                     {
  205.                         BlockCopy((void *)pInterfaceDescriptor, (void *)(&(pCompositePB->interfaceDescriptors[i])), (Size)(pInterfaceDescriptor->length));
  206.                     }
  207.                     else                /* if GetInterfaceDescriptor returned an error, then set the length to zero (so we know later) */
  208.                     {
  209.                         pCompositePB->interfaceDescriptors[i].length = 0;
  210.                     }
  211.                 }
  212.                 pCompositePB->interfaceIndex = 0;
  213.                 pCompositePB->interfaceCount = pCompositePB->partialConfigDescriptor.numInterfaces;
  214.                 pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  215.                 break;
  216.                 
  217.             case kNewInterfaceRef:
  218.                 /* save the new interface ref for this interface */
  219.                 pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex] = pCompositePB->pb.usbReference;
  220.                 
  221.                 /* only install the interface driver if we had a valid interface descriptor */
  222.                 if (pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex].length != 0)
  223.                 {
  224.                     USBExpertInstallInterfaceDriver(pCompositePB->interfaceRefArray[pCompositePB->interfaceIndex], &pCompositePB->deviceDescriptor, &pCompositePB->interfaceDescriptors[pCompositePB->interfaceIndex], pCompositePB->deviceRef, 0);
  225.                 }
  226.                 
  227.                 /* advance to the next interface */
  228.                 pCompositePB->interfaceIndex++;
  229.                 
  230.                 /* if there's more interfaces, then just keep cycling through kNewInterfaceRef */
  231.                 if (pCompositePB->interfaceIndex < pCompositePB->interfaceCount)
  232.                 {
  233.                     pCompositePB->pb.usbRefcon = kNewInterfaceRef;
  234.                 }
  235.                 else
  236.                 {
  237.                     pCompositePB->pb.usbRefcon = kExitDriver;
  238.                 }
  239.                 break;
  240.             
  241.             default:
  242.                 USBExpertFatalError(pCompositePB->pb.usbReference, kUSBInternalErr, "\pComposite Driver - Transaction completed with a bad refcon value", pCompositePB->pb.usbRefcon);
  243.                 pCompositePB->pb.usbRefcon = kExitDriver;
  244.                 break;
  245.         }
  246.     }
  247.     if (!(pCompositePB->pb.usbRefcon & kExitDriver))
  248.         CompositeDeviceInitiateTransaction(pb);
  249.  
  250.     pCompositePB->okayToFinalizeFlag = true;
  251.     pCompositePB->disposeCompletedFlag = true;
  252. }
  253.  
  254.  
  255.